/*
Time the operation of the filebuff/write_bytes.c program (provided in the source
code distribution for this book) for various buffer sizes and file systems.
 */

/*
./a.out file 100000000 100  0,38s user 1,16s system 99% cpu 1,542 total
./a.out file 100000000 1000000  0,00s user 0,05s system 98% cpu 0,053 total
-DUSE_FSYNC -DFUSE_FDATASYNC
./a.out file 100000000 1000000  0,00s user 0,13s system 16% cpu 0,844 total
 */

#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <tgmath.h>

int
main(int argc, char *argv[])
{
    size_t bufSize, numBytes, thisWrite, totWritten;
    char *buf;
    int fd, openFlags;

    if (argc != 4 || strcmp(argv[1], "--help") == 0)
      exit(EXIT_FAILURE);

    numBytes = atoll(argv[2]);
    bufSize = atoll(argv[3]);

    buf = malloc(bufSize);
    if (buf == NULL)
        exit(EXIT_FAILURE);

    openFlags = O_CREAT | O_WRONLY;

#if defined(USE_O_SYNC) && defined(O_SYNC)
    openFlags |= O_SYNC;
#endif

    fd = open(argv[1], openFlags, S_IRUSR | S_IWUSR);
    if (fd == -1)
        exit(EXIT_FAILURE);

    for (totWritten = 0; totWritten < numBytes;
            totWritten += thisWrite) {
        thisWrite = fmin(bufSize, numBytes - totWritten);

        if (write(fd, buf, thisWrite) != thisWrite)
            exit(EXIT_FAILURE);

#ifdef USE_FSYNC
        if (fsync(fd))
            exit(EXIT_FAILURE);
#endif
#ifdef USE_FDATASYNC
        if (fdatasync(fd))
            exit(EXIT_FAILURE);
#endif
    }

  if (close(fd) == -1)
        exit(EXIT_FAILURE);

  return EXIT_SUCCESS;
}
